#ifndef BIOSIGNAL_HH
#define BIOSIGNAL_HH

#include <biosignal/sourcesignal.h>
#include <biosignal/datetime.h>
#include <biosignal/signalslice.h>
#include <biosignal/montage/montage.h>

#include <string>
#include <sstream>
#include <list>
#include <vector>
#include <stdexcept>
#include <exception>
#include <tr1/memory>


namespace biosignal
{

using namespace std::tr1;

typedef std::vector< SourceSignal::SourceSignal_sptr > SignalsGroup;

typedef shared_ptr<std::istream> istream_ptr;

class BadTimePeriod : public std::exception
{
    virtual const char* what() const throw()
    {
        return "The time period does not fall into the signal recording time";
    }
};

class BadTimePoint : public std::exception
{
    virtual const char* what() const throw()
    {
        return "The time point does not fall into the signal recording time";
    }
};

class NotImplementedException : public std::runtime_error
{
public:
    NotImplementedException(const string& function) : std::runtime_error( function + "Not Implemented Yet") {}
};

class BioSignal
{
public:
    BioSignal(const char* file_name);
    virtual ~BioSignal();

    const SignalsGroup& signals_group() const;

    SignalSlice signal_slice( TimePeriod time_period ) const throw (BadTimePeriod);
    SignalSlice signal_slice( TimeOffset start, TimeOffset end ) const throw (BadTimePeriod);
    SignalSlice signal() const;

    TimePeriod recording_time() const;

    shared_ptr<const montage::Montage> ref_montage() const;
    shared_ptr<const montage::Montage> avg_ref_montage() const;

    virtual void show_header_info(std::ostream& os) const = 0;
    virtual long get_nr_dataframes() const = 0;
    virtual TimePeriod dataframe_time_period(TimePoint time) const throw (BadTimePoint) = 0;

    friend class DataFrameIterator;
protected:

    virtual DataFrame* create_dataframe( TimePeriod bounds, shared_ptr<const montage::Montage> montage ) const = 0;
    TimePeriod m_recording_time;
    string file_name_;

    void add_signals_info(std::list<biosignal::SourceSignal*> signals_info);
    SignalsGroup m_signals_group;
};



//typedef std::tr1::shared_ptr<BioSignal> BioSignal_sptr;
//typedef std::tr1::weak_ptr<BioSignal> BioSignal_wptr;


//TODO throw exception when the file can't be read
const BioSignal* load( string file_name );

string version();

}
#endif // BIOSIGNAL_HH
